# -*- coding: utf-8 -*-
"""
    @Author：SimpleTree
    @date：2025/4/26 21:33
    @desc:
"""
import logging
from functools import wraps

from flask import jsonify, make_response, request as flask_request
from itsdangerous import URLSafeTimedSerializer

from api import settings
from api.utils import get_uuid


def get_json_result(code=settings.RetCode.SUCCESS, message="success", data=None):
    response = {"code": code, "message": message, "data": data}
    return jsonify(response)


def server_error_response(e):
    logging.exception(e)
    try:
        if e.code == 401:
            return get_json_result(code=401, message=repr(e))
    except BaseException:
        pass
    if len(e.args) > 1:
        return get_json_result(
            code=settings.RetCode.EXCEPTION_ERROR,
            message=repr(e.args[0]),
            data=e.args[1]
        )
    if repr(e).find("index_not_found_exception") >= 0:
        return get_json_result(
            code=settings.RetCode.EXCEPTION_ERROR,
            message="No chunk found, please upload file and parse it.")

    # repr 是 Python 的内置函数，其用途是返回一个对象的字符串表示形式，
    # 这个字符串表示形式通常是一个可以用来重新创建该对象的合法 Python 表达式。
    # str：目标是生成一个对用户友好的字符串表示，主要用于打印和显示。
    # repr：目标是生成一个对开发者友好的字符串表示，这个字符串可以用来重新创建该对象。一般来说，repr 输出的字符串更加详细，包含更多的对象信息
    return get_json_result(code=settings.RetCode.EXCEPTION_ERROR, message=repr(e))


def construct_response(code=settings.RetCode.SUCCESS, message="success", data=None, auth=None):
    result_dict = {"code": code, "message": message, "data": data}
    response_dict = {}
    for key, value in result_dict.items():
        if value is None and key != "code":
            continue
        else:
            response_dict[key] = value
    response = make_response(jsonify(response_dict))
    if auth:
        response.headers["Authorization"] = auth
    response.headers["Access-Control-Allow-Origin"] = "*"
    response.headers["Access-Control-Allow-Method"] = "*"
    response.headers["Access-Control-Allow-Headers"] = "*"
    response.headers["Access-Control-Allow-Headers"] = "*"
    response.headers["Access-Control-Expose-Headers"] = "Authorization"
    return response


def get_data_error_result(code=settings.RetCode.DATA_ERROR,
                          message="Sorry! Data missing"):
    logging.exception(Exception(message))
    result_dict = {
        "code": code,
        "message": message
    }
    response = {}
    for key, value in result_dict.items():
        if value is None and key != "code":
            continue
        else:
            response[key] = value
    return jsonify(response)


def server_error_response(e):
    logging.exception(e)
    try:
        if e.code == 401:
            return get_json_result(code=401, message=repr(e))
    except BaseException:
        pass
    if len(e.args) >1:
        return get_json_result(
            code=settings.RetCode.EXCEPTION_ERROR,
            message=repr(e.args[0]),
            data=e.args[1]
        )
    if repr(e).find("index_not_found_exception") >= 0:
        return get_json_result(
            code=settings.RetCode.EXCEPTION_ERROR,
            message="No chunk found, please upload file and parse it."
        )
    return get_json_result(code=settings.RetCode.EXCEPTION_ERROR, message=repr(e))


def validate_request(*args, **kwargs):
    def wrapper(func):
        @wraps(func)
        def decorated_function(*_args, **_kwargs):
            input_arguments = flask_request.json or flask_request.form.to_dict()
            no_arguments = []
            error_arguments = []
            for arg in args:
                if arg not in input_arguments:
                    no_arguments.append(arg)
            for k, v, in kwargs.items():
                config_value = input_arguments.get(k, None)
                if config_value is None:
                    no_arguments.append(k)
                elif isinstance(v, (tuple, list)):
                    if config_value not in v:
                        error_arguments.append((k, set(v)))
                elif config_value != v:
                    error_arguments.append((k, v))
            if no_arguments or error_arguments:
                error_string = ""
                if no_arguments:
                    error_string += "required argument are missing: {};".format(".".join(no_arguments))
                if error_arguments:
                    error_string += "required argument values: {}".format(
                        ",".join(["{}={}".format(k, v) for k, v in error_arguments]))
                return get_json_result(
                    code=settings.RetCode.ARGUMENT_ERROR,
                    message=error_string
                    )
            return func(*_args, **_kwargs)
        return decorated_function
    return wrapper


def not_allowed_parameters(*params):
    def decorator(f):
        def wrapper(*args, **kwargs):
            input_arguments = flask_request.json or flask_request.form.to_dict()
            for param in params:
                if param in input_arguments:
                    return get_json_result(
                        code=settings.RetCode.ARGUMENT_ERROR,
                        message=f"Parameter {param} isn't allowed")
            return f(*args, **kwargs)
        return wrapper
    return decorator


def generate_confirmation_token(tenant_id):
    serializer = URLSafeTimedSerializer(tenant_id)
    return "ragflow-" + serializer.dumps(get_uuid(), salt=tenant_id)[2:34]

